package tool

import (
	"bytes"
	"cloud-disk/core/helper"
	"context"
	"fmt"
	"github.com/tencentyun/cos-go-sdk-v5"
	"net/http"
	"net/url"
	"os"
	"path"
)

type Cos struct {
	Addr      string
	SecretID  string
	SecretKey string
	Client    *cos.Client
}

type CosConfig struct {
	Addr      string
	SecretID  string
	SecretKey string
}

func NewCos(config *CosConfig) *Cos {
	u, _ := url.Parse(config.Addr)
	b := &cos.BaseURL{BucketURL: u}
	client := cos.NewClient(b, &http.Client{
		Transport: &cos.AuthorizationTransport{
			SecretID:  config.SecretID,
			SecretKey: config.SecretKey,
		},
	})
	return &Cos{
		Addr:      config.Addr,
		SecretID:  config.SecretID,
		SecretKey: config.SecretKey,
		Client:    client,
	}
}

func (cos Cos) CosUpload(r *http.Request, addr string) (string, error) {
	file, header, err := r.FormFile("file")
	if err != nil {
		return "", err
	}

	key := "cloud-disk/" + helper.GetUUID() + path.Ext(header.Filename)
	_, err = cos.Client.Object.Put(
		context.Background(), key, file, nil,
	)
	if err != nil {
		return "", err
	}

	return cos.Client.Object.GetObjectURL(key).String(), nil
}

//InitiateMultipartUpload 初始化分片上传
func (cos Cos) InitiateMultipartUpload(r *http.Request) (uploadID string, key string, err error) {
	_, header, err := r.FormFile("file")
	if err != nil {
		return "", "", err
	}

	key = "cloud-disk/" + helper.GetUUID() + path.Ext(header.Filename)
	// 可选opt,如果不是必要操作，建议上传文件时不要给单个文件设置权限，避免达到限制。若不设置默认继承桶的权限。
	v, _, err := cos.Client.Object.InitiateMultipartUpload(context.Background(), key, nil)
	if err != nil {
		return "", "", err
	}
	UploadID := v.UploadID
	return UploadID, key, err
}

//UploadPart 分片上传
func (cos Cos) UploadPart(uploadId, key string, chunk []string) (tags []string, err error) {
	for i, ck := range chunk {
		f, err := os.ReadFile(ck)
		if err != nil {
			return nil, err
		}
		fmt.Println(i + 1)

		resp, err := cos.Client.Object.UploadPart(
			context.Background(), key, uploadId, i+1, bytes.NewReader(f), nil,
		)
		if err != nil {
			return nil, err
		}
		PartETag := resp.Header.Get("ETag")
		tags = append(tags, PartETag)
	}

	return tags, nil
}

//CompleteMultipartUpload 完成分片上传
func (mycos Cos) CompleteMultipartUpload(key string, UploadID string, tags []string) (url string, err error) {
	opt := &cos.CompleteMultipartUploadOptions{}
	for _, tag := range tags {
		opt.Parts = append(opt.Parts, cos.Object{
			PartNumber: 1, ETag: tag},
		)
	}
	_, _, err = mycos.Client.Object.CompleteMultipartUpload(
		context.Background(), key, UploadID, opt,
	)

	if err != nil {
		return "", err
	}
	return mycos.Client.Object.GetObjectURL(key).String(), nil
}
